package com.jwsoft.manager.core.integration.addressParse;

import cn.hutool.core.convert.Convert;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheType;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bifang.engine.cache.jetcache.utils.JetCacheUtils;
import com.jwsoft.manager.common.constant.EduCache;
import com.jwsoft.manager.common.vo.addressParse.Address;
import com.jwsoft.manager.core.dao.model.EduAddressTreeOriginal;
import com.jwsoft.manager.core.dao.service.EduAddressTreeOriginalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AddressDataImpl implements AddressDataLoader {
    @Autowired
    EduAddressTreeOriginalService eduAddressTreeOriginalService;
    @Override
    public List<Address> loadData() {
        Cache<String,List<Address>> cache = JetCacheUtils.create(EduCache.EDU_ADDRESS_TREE_ALL, CacheType.BOTH, Duration.ofDays(30),Duration.ofSeconds(300));
        if (cache!=null){
            List<Address> list=cache.get("all");
            if (!CollectionUtils.isEmpty(list)){
                return list;
            }
        }
        LambdaQueryWrapper<EduAddressTreeOriginal> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.select(EduAddressTreeOriginal::getAddressId,EduAddressTreeOriginal::getAreaCode,EduAddressTreeOriginal::getAreaName,EduAddressTreeOriginal::getAreaType,EduAddressTreeOriginal::getParentId,EduAddressTreeOriginal::getSearchTerm);
        List<EduAddressTreeOriginal> list=eduAddressTreeOriginalService.list(queryWrapper);
        List<Address> addList= Convert.toList(Address.class,list);
        List<Address> addressList = builderTreeList(addList);
        cache.put("all",addressList);
        return addressList;
    }


    // 优化list转tree
    private List<Address> builderTreeList(List<Address> addList){
        if (addList == null || addList.isEmpty()) {
            return new ArrayList<>();
        }
        //最后需要返回的树形list结构，根节点的parentId为0
        List<Address> respTreeNodeList = new LinkedList<>();
        //存储所有节点的id，用来判断是否为根节点数据
        Set<Long> idSet = new HashSet<>(addList.size());
        // 拷贝数据
        for (Address address : addList) {
            idSet.add(address.getAddressId());
            respTreeNodeList.add(address);
        }
        //将list进行分组，按照父节点id进行分组
        Map<Long, List<Address>> parentMap = addList.stream().collect(Collectors.groupingBy(Address::getParentId));
        // 设置children，并从根节点移出不是父节点的数据
        Iterator<Address> iterator = respTreeNodeList.iterator();
        Address node;
        while (iterator.hasNext()) {
            node = iterator.next();
            // 获取当前结点的子节点集合
            node.setChildren(parentMap.get(node.getAddressId()));
            // 如果父id在id集合中存在，则说明他不是根节点，移除
            if (idSet.contains(node.getParentId())) {
                iterator.remove();
            }
        }
        return respTreeNodeList;
    }
    /**
     * 将List重组为数
     *
     * @param taskDTOList DTO集合
     * @return List<TreeEntity>
     */
    public  List<Address> constructTaskDTOToTree(
            List<Address> taskDTOList, Long resultTask) {
        if (CollectionUtils.isEmpty(taskDTOList)) {
            return new ArrayList<>();
        }
        // key:父节点ID value:子节点集合
        Map<Long, List<Address>> taskDTOMap = new HashMap<>();

        // 将List重组到Map中
        taskDTOList.forEach(
                dto -> {
                    List<Address> tempTaskDTOList = taskDTOMap.get(dto.getParentId());
                    if (tempTaskDTOList == null) {
                        tempTaskDTOList = new ArrayList<Address>();
                        taskDTOMap.put(dto.getParentId(), tempTaskDTOList);
                    }
                    tempTaskDTOList.add(dto);
                });

        // 顶级节点集合

        List<Address> resultTaskDTOList = taskDTOMap.get(resultTask);
        if (CollectionUtils.isEmpty(resultTaskDTOList)) {
            resultTaskDTOList = taskDTOMap.get("0");
        }

        recurTaskDTOList(resultTaskDTOList, taskDTOMap);

        return resultTaskDTOList;
    }

    /**
     * 将重组好的Map进行树形结构处理
     *
     * @param taskDTOList 父节点集合(不一定是顶级节点 因为会递归调用)
     * @param sourceMap 组装好的Map集合
     */
    public  void recurTaskDTOList(
            List<Address> taskDTOList, Map<Long, List<Address>> sourceMap) {
        if (CollectionUtils.isEmpty(taskDTOList)) {
            return;
        }
        taskDTOList.forEach(
                dto -> {
                    List<Address> children=sourceMap.get(dto.getAddressId());
                    dto.setChildren(children);

                    recurTaskDTOList(dto.getChildren(), sourceMap);
                });
    }
}
